(function (line, browser, support, document, global) {
    var dom = line.dom = line.dom || {};
    var isIE8 = (browser.ie == 8),
        borderMap = {
            thin:(isIE8) ? '1px' : '2px',
            medium:(isIE8) ? '3px' : '4px',
            thick:(isIE8) ? '5px' : '6px'
        },
        rHasUnit = /width|height|top|right|bottom|left|size|margin|padding/i,
        cssNumber = ['lineHeight'];

    function addPixel(name, value) {
        if (line.isNumber(value) && rHasUnit.test(name) && cssNumber.indexOf(name) === -1) {
            value += 'px';
        }
        return value;
    }

    var cssHooks = (function () {
        var hook = {
            'float':{
                setter:function (element, value) {
                    element.style.cssFloat = value;
                },
                getter:function (element, computed) {
                    return getNormalStyle(element, 'cssFloat', computed);
                },
                remove:function (el) {
                    el.style.removeAttribute('cssFloat');
                }
            }
        };
        if (browser.ie) {
            hook['float'] = {
                setter:function (element, value) {
                    element.style.styleFloat = value;
                },
                getter:function (element, computed) {
                    return getNormalStyle(element, 'styleFloat', computed);
                },
                remove:function (el) {
                    el.style.removeAttribute('styleFloat');
                }
            };
            //browser.version <9?
            if (!support['opacity']) {
                //Thanks jQuery && Qwrap && JerryQu
                var ropacity = /opacity=([^)]*)/,
                    ralpha = /alpha\([^)]*\)/i;
                hook['opacity'] = {
                    setter:function (element, value) {
                        var style = element.style,
                            currentStyle = element.currentStyle;
                        // IE has trouble with opacity if it does not have layout
                        // Force it by setting the zoom level
                        style.zoom = 1;
                        var opacity = "alpha(opacity=" + value * 100 + ")",
                            filter = currentStyle && currentStyle.filter || style.filter || "";
                        style.filter = ralpha.test(filter) ?
                            filter.replace(ralpha, opacity) :
                            filter + " " + opacity;
                    },
                    getter:(function () {
                        var getOpacity = function (curCls) {
                            if (ropacity.test(curCls)) {
                                return parseFloat(RegExp.$1) / 100;
                            }
                        };
                        return function (element, computed) {
                            var curCls = getNormalStyle(element, 'filter');
                            if (computed) {
                                return curCls ? getOpacity(curCls) : 1;
                            } else {
                                return curCls ? getOpacity(curCls) : '';
                            }
                        };
                    }()),
                    remove:function (element) {
                        var style = element.style,
                            currentStyle = element.currentStyle,
                            filter = currentStyle && currentStyle.filter || style.filter || "";
                        if (ralpha.test(filter)) {
                            style.filter = filter.replace(ralpha, '');
                        }
                        style.removeAttribute('opacity');
                    }
                }
            }
        }
        return hook;
    }());

    function getNormalStyle(element, name, computed) {
        var result;
        if (computed) {
            var window = global || element.ownerDocument.defaultView,
                style = window.getComputedStyle && window.getComputedStyle(element, null);
            result = (style && style.getPropertyValue(name)) || element.currentStyle[name];
        } else {
            result = element.style[name];
        }
        return result || null;
    }

    function setSize(element, name, value) {
        var size = 0;
        element.style[name] = value;
        size = (name === 'height') ? element.offsetHeight : element.offsetWidth;
        if (size > value) {
            value = value - (size - value);
            element.style[name] = value;
        }
        return element;
    }

    line.extend(dom, {
        getStyle:(function () {
            function normalize(result) {
                return borderMap[result] || result;
            }
            return function (element, name, computed) {
                name = line.decamelize(name);
                var result,
                    hook = cssHooks[name];
                if (hook) {
                    if ('getter' in hook) {
                        result = hook.getter(element);
                    }
                } else {
                    result = getNormalStyle(element, name, computed);
                }
                return normalize(result);
            };
        }()),

        setStyle:function (element, name, value) {
            name = line.camelize(name);
            value = addPixel(name, value);
            var hook = cssHooks[name];
            if (hook) {
                if ('setter' in hook) {
                    hook.setter(element, value);
                }
            } else {
                element.style[name] = value;
            }
        },
        setStyles:(function () {
            var objToCssText = function (element, styles) {
                var prop, val, temp = [';'], hook;
                for (prop in styles) {
                    prop = line.camelize(prop);
                    val = addPixel(prop, obj[prop]);
                    hook = cssHooks[prop];
                    if (hook && 'setter' in hook) {
                        hook.setter(element, val);
                        delete styles[prop];
                        continue;
                    }
                    temp.push(prop, ':', val, ';');
                }
                return temp.join('');
            };
            return function (element, styles) {
                var newCls = objToCssText(element, styles);
                if (';' !== newCls) {
                    element.style.cssText += newCls;
                }
            };
        }()),
        hasStyle:function (element, name) {
            return name in element.style;
        },
        removeStyle:function (element, name) {
            name = line.camelize(name);
            var hook = cssHooks[name];
            if (hook) {
                if ('remove' in hook) {
                    hook.remove(element);
                }
            } else {
                element.style.removeAttribute(name);
            }
        },
        getSize:function (element) {
            return {
                width:element.offsetWidth,
                height:element.offsetHeight
            };
        },

        setSize:function (element, obj) {
            setSize(element, 'width', obj.width);
            setSize(element, 'height', obj.height);
        },
        getWidth:function (element) {
            return element.offsetWidth;
        },
        setWidth:function (element, value) {
            setSize(element, 'width', value);
        },
        getHeight:function (element) {
            return element.offsetHeight;
        },
        setHeight:function (element, value) {
            setSize(element, 'height', value);
        },
        //TODO:has some bug,need to be fixed.
        positoin:function (element) {
            return {
                left:element.offsetLeft,
                top:element.offsetTop
            };
        },
        getScroll:function (doc) {
            doc = doc || document;
            return {
                left:Math.max((window.pageXOffset || 0), doc.documentElement.scrollLeft, doc.body.scrollLeft),
                top:Math.max((window.pageYOffset || 0), doc.documentElement.scrollTop, doc.body.scrollTop)
            };
        },
        setScroll:function (left, top, doc) {
            var win = dom.getWindow(doc);
            win.scrollTo(left, top);
        },
        //thanks qwrap/yui
        offset:(function () {
            var calcBorders = function (node, xy) {
                var t = parseInt(dom.getStyle(node, 'borderTopWidth', true), 10) || 0,
                    l = parseInt(dom.getStyle(node, 'borderLeftWidth', true), 10) || 0;
                if (browser.firefox) {
                    if (/^t(?:able|d|h)$/i.test(node.tagName)) {
                        t = l = 0;
                    }
                }
                xy[0] += l;
                xy[1] += t;
                return xy;
            };
            if (support['getBoundingClientRect']) {
                return function (node) {
                    var doc = node.ownerDocument,
                        docRect = dom.getDocRect(doc),
                        scrollLeft = docRect.scrollX,
                        scrollTop = docRect.scrollY,
                        box = node.getBoundingClientRect(),
                        xy = [box.left, box.top],
                        off1,
                        off2;
                    if (browser.ie) {
                        off1 = doc.documentElement.clientLeft;
                        off2 = doc.documentElement.clientTop;
                        if (!browser.isStrict) {
                            off1 = doc.body.clientLeft;
                            off2 = doc.body.clientTop;
                        }
                        xy[0] -= off1;
                        xy[1] -= off2;
                    }
                    if (scrollTop || scrollLeft) {
                        xy[0] += scrollLeft;
                        xy[1] += scrollTop;
                    }
                    return {
                        left:xy[0],
                        top:xy[1]
                    };
                };
            } else {
                return function (node) {
                    var xy = [node.offsetLeft, node.offsetTop],
                        parentNode = node.parentNode,
                        doc = node.ownerDocument,
                        docRect = dom.getDocRect(doc),
                        bCheck = !!(browser.firefox || parseFloat(browser.webkit) > 519),
                        scrollTop = 0,
                        scrollLeft = 0;
                    while ((parentNode = parentNode.offsetParent)) {
                        xy[0] += parentNode.offsetLeft;
                        xy[1] += parentNode.offsetTop;
                        if (bCheck) {
                            xy = calcBorders(parentNode, xy);
                        }
                    }
                    if (dom.getStyle(node, 'position', true) != 'fixed') {
                        parentNode = node;
                        while (parentNode = parentNode.parentNode) {
                            scrollTop = parentNode.scrollTop;
                            scrollLeft = parentNode.scrollLeft;
                            if (browser.firefox && (dom.getStyle(parentNode, 'overflow', true) !== 'visible')) {
                                xy = calcBorders(parentNode, xy);
                            }
                            if (scrollTop || scrollLeft) {
                                xy[0] -= scrollLeft;
                                xy[1] -= scrollTop;
                            }
                        }
                    }
                    xy[0] += docRect.scrollX;
                    xy[1] += docRect.scrollY;
                    return {
                        left:xy[0],
                        top:xy[1]
                    };
                };
            }
        }()),
        //thanks to qwrap/yui
        getDocRect:function (doc) {
            doc = doc || document;
            var window = dom.getWindow(doc),
                root = doc.documentElement,
                h = window.innerHeight || 0,
                w = window.innerWidth || 0,
                scrollW = root.scrollWidth,
                scrollH = root.scrollHeight,
                scrollXY = dom.getScroll(doc);
            if (!browser.isStrict) {
                root = doc.body;
                scrollW = root.scrollWidth;
                scrollH = root.scrollHeight;
            }
            if (browser.compatMode && !browser.opera) { // IE, Gecko
                w = root.clientWidth;
                h = root.clientHeight;
            }
            scrollW = Math.max(scrollW, w);
            scrollH = Math.max(scrollH, h);
            return {
                width:w,
                height:h,
                scrollWidth:scrollW,
                scrollHeight:scrollH,
                scrollX:scrollXY.left,
                scrollY:scrollXY.top
            };
        }
    });
})(line, line.browser, line.support, document, window);